/* mmuE500Lib.h - mmu library for PowerPC E500 series */

/* Copyright 2001-2004  Wind River Systems, Inc. */

/*
modification history
--------------------
01i,19jul05,dtr  Implement 36bit rpn.
01h,11nov04,dtr  Add user permission flags for static TLBs.
01g,07oct04,mdo  Documentation fixes for apigen.
01f,09apr04,dtr  Add in MMU_LOCK mask and bit field in Pte.
01e,18mar04,dtr  Mods fixes after formal inspection.
01d,09feb04,dtr  Fix protection bits.
01c,30jan04,mil  Updated for Base6.
01b,13jun03,mil  Added TLB sizes.
01a,07jan03,dtr  Adding support for static TLB entries.
*/

/*
DESCRIPTION

This header contains the public interface to the PowerPC E500 Core Memory
Management Library. It also defines private (internal) structures and
macros used to manipulate the E500 MMU.

Theory: the vmBaseLib and vmLib provide an application programmer
interface to the memory management and protection features of the E500
MMU. With the help of the aimMmuLib and mmuE500Lib layers, a data
structure is maintained which stores per-page attributes: validity,
protection, cacheability, and address translation. This data structure
represents each page as a page table entry (PTE).

The E500 MMU has two levels.  In level 1, instruction and data are
split, while they are unified in level 2.  Level 1 is maintained by
the hardware and level 2 is maintained by the OS.  The number of entries
are as follows:

Name      Level   Type No of pg sizes Assoc     #entries     filled by
I-L1VSP     L1    Instr     9         Full         4         TLB1 hit
I-L1TLB4K   L1    Instr   1(4k)       4-way        64         TLB0 hit
D-L1VSP     L1    Data      9         Full         4         TLB1 hit
D-L1TLB4K   L1    Data    1(4k)       4-way        64         TLB0 hit
TLB1        L2    I/D       9         Full        16         s/w tlbwe
TLB0        L2    I/D     1(4k)       2-way       256         s/w tlbwe

The VSP (variable sized page) are used as static entries like the BATs,
while the 4k page are dynamic entries that gets loaded with the PTEs.
When a TLB miss occur in TLB0, an exception occurs and the OS walks the
data structure and copies a PTE into a TLB0 entry.  Hence, TLB1 is 
filled with mapping from the sysStaticTlbDesc[] array, and TLB0 is 
filled with mapping from the sysPhysMemDesc[] array.

Note that the E500 MMU cannot be turned off.  Translation occurs at
all time, which it uses also the IS and DS bits while deciding a hit.
Real mode is simulated with both IS and DS bits set to zero.

This file provides data needed to coordinate the mmuE500Lib layer with
the aimMmuLib and vmLib/vmBaseLib layers, as well as definitions needed
to configure the sysStaticTlbDesc[] array.
*/

#ifndef __INCmmuE500Libh
#define __INCmmuE500Libh

#ifdef __cplusplus
extern "C" {
#endif

/* defines */

#define N_TLB_ENTRIES_BITS	8		/* # TLB0: read TLB0CFG */
#define N_TLB_ENTRIES		256		/* # TLB0: read TLB0CFG */

#define MMU_PAGE_SIZE		0x1000		/* pages are 4K bytes */

/*
 * MMU_I_ADDR_TRANS and MMU_D_ADDR_TRANS are used in the mmuE500Lib /
 * mmuPpcALib & cacheALib call interface. They are not useful at the
 * application programming level.
 */

#define MMU_I_ADDR_TRANS	0
#define MMU_D_ADDR_TRANS	1

/*
 * MMU_INST and MMU_DATA are used at the usrMmuInit
 * interface.  They are not useful at the application programming
 * level.
 */

#define MMU_INST		0x01
#define MMU_DATA		0x02

/*
 * MMU_STATE attributes
 *
 */

/* V, WIMGE bits */

#define MMU_STATE_VALID				0x80000000
#define MMU_STATE_VALID_NOT			0x00000000
#define MMU_STATE_LOCK				0x00800000
#define MMU_STATE_UNLOCK			0x00000000
#define MMU_STATE_CACHEABLE_WRITETHROUGH	0x00000010
#define MMU_STATE_CACHEABLE_COPYBACK		0x00000000
#define MMU_STATE_CACHEABLE			0x00000000
#define MMU_STATE_CACHEABLE_NOT			0x00000008
#define MMU_STATE_MEM_COHERENCY  		0x00000004
#define MMU_STATE_MEM_COHERENCY_NOT		0x00000000
#define MMU_STATE_GUARDED			0x00000002
#define MMU_STATE_GUARDED_NOT			0x00000000
#define MMU_STATE_ENDIAN_BIG			0x00000000
#define MMU_STATE_ENDIAN_LITTLE			0x00000001

#define MMU_STATE_MASK_VALID			0x80000000
#define MMU_STATE_MASK_LOCK			0x00800000
#define MMU_STATE_MASK_WIMG                     0x0000001F
#define MMU_STATE_MASK_WRITETHROUGH		0x00000010
#define MMU_STATE_MASK_CACHEABLE    		0x00000018
#define MMU_STATE_MASK_MEM_COHERENCY  		0x00000004
#define MMU_STATE_MASK_GUARDED			0x00000002
#define MMU_STATE_MASK_ENDIAN			0x00000001

/* UX/SX, UW/SW, UR/SR bits */

  /* drice - need to look at these values */
#define MMU_STATE_EXECUTE			0x00003000
#define MMU_STATE_EXECUTE_NOT			0x00000000
#define MMU_STATE_WRITABLE			0x00000c00
#define MMU_STATE_WRITABLE_NOT			0x00000000
#define MMU_STATE_MASK_EXECUTE			0x00003000
#define MMU_STATE_MASK_WRITABLE			0x00000c00
#define MMU_STATE_MASK_WRITABLE_EXECUTE         0x00003c00
#define MMU_STATE_MASK_WIMG_WRITABLE_EXECUTE    0x00000000 
#define MMU_STATE_MASK_PROTECTION		0x00003f00
#define MMU_STATE_PROTECTION_BIT_SHIFT          8
/*
 * The next most significant MMU_PAGE_INDEX_BITS bits of the virtual
 * address are used as an index into the Page Table.
 *
 * The next most significant bits of the virtual address are used as an
 * index into the Page Table.  Note that MMU_PAGE_INDEX_BITS_MAX
 * describes the maximum number of bits to be used as a index to look up
 * an entry in the page table. 
 *
 * Each entry is of size 2 ^ MMU_PAGE_ENTRY_BITS, which is the size of
 * an MMUE500_PTE.
 */

#define MMU_PAGE_INDEX_BITS_MAX	10	/* number of bits in index */
#define MMU_PAGE_TBL_ENTRIES_MAX (0x1 << MMU_PAGE_INDEX_BITS_MAX)
					/* max number of page table entries */
#define MMU_PAGE_ENTRY_BITS	4    /* MMUE500_PTE size in bytes as pwr of 2 */

/*
 * Each context's MMU pages are mapped using a two-level page table
 * scheme. The level 1 table is called the REGION table and the level
 * 2 table is called a PAGE table.
 *
 * The most significant MMU_REGION_INDEX_BITS bits of the virtual
 * address are used as an index into the Region Table. Each entry is of
 * size 2 ^ MMU_REGION_ENTRY_BITS, typically a pointer to a PAGE table.
 */

#define MMU_REGION_INDEX_BITS	10	/* number of bits in index */
#define MMU_REGION_TBL_ENTRIES	(0x1 << MMU_REGION_INDEX_BITS)
					/* number of regions in table */
#define MMU_REGION_ENTRY_BITS	2	/* size in bytes as pwr of 2 */

#if defined(PPC_e500v2)
#define MMUE500_NO_BITS_PHYS_ADDR       36
#endif

/*
 * Protection Bits
 *
 * Each TLB entry controls access to one page of memory. The protection
 * mode is controlled by 6 bits in the TLB word, one for each of Read,
 * Write, Execute for Supervisor and User.
 *
 * These protection bits are mapped directly into MMU_STATE_* macros,
 * defined below:
 */

/* MMU_STATE_* protection mode sub-fields, mapping <<8 with hardware */

#define _MMU_UX			0x00002000
#define _MMU_SX			0x00001000
#define _MMU_UW			0x00000800
#define _MMU_SW			0x00000400
#define _MMU_UR			0x00000200
#define _MMU_SR			0x00000100

#define _MMU_URWX	 	   (_MMU_UR | _MMU_UW | _MMU_UX)

/* MMU_STATE_* protection modes macros */

#define MMU_STATE_SUP_R		   (_MMU_SR)
#define MMU_STATE_SUP_RW	   (_MMU_SR|_MMU_SW)
#define MMU_STATE_SUP_RX	   (_MMU_SR|        _MMU_SX)
#define MMU_STATE_SUP_RWX	   (_MMU_SR|_MMU_SW|_MMU_SX)

#define MMU_STATE_SUP_R_USR_R	   (MMU_STATE_SUP_R   | _MMU_UR)
#define MMU_STATE_SUP_RW_USR_R     (MMU_STATE_SUP_RW  | _MMU_UR)
#define MMU_STATE_SUP_RX_USR_R     (MMU_STATE_SUP_RX  | _MMU_UR)
#define MMU_STATE_SUP_RWX_USR_R    (MMU_STATE_SUP_RWX | _MMU_UR)

#define MMU_STATE_SUP_R_USR_W	   (MMU_STATE_SUP_R   | _MMU_UW)
#define MMU_STATE_SUP_RW_USR_W     (MMU_STATE_SUP_RW  | _MMU_UW)
#define MMU_STATE_SUP_RX_USR_W     (MMU_STATE_SUP_RX  | _MMU_UW)
#define MMU_STATE_SUP_RWX_USR_W    (MMU_STATE_SUP_RWX | _MMU_UW)

#define MMU_STATE_SUP_R_USR_RW	   (MMU_STATE_SUP_R   | _MMU_UR | _MMU_UW)
#define MMU_STATE_SUP_RW_USR_RW    (MMU_STATE_SUP_RW  | _MMU_UR | _MMU_UW)
#define MMU_STATE_SUP_RX_USR_RW    (MMU_STATE_SUP_RX  | _MMU_UR | _MMU_UW)
#define MMU_STATE_SUP_RWX_USR_RW   (MMU_STATE_SUP_RWX | _MMU_UR | _MMU_UW)

#define MMU_STATE_SUP_R_USR_X	   (MMU_STATE_SUP_R   | _MMU_UX)
#define MMU_STATE_SUP_RW_USR_X     (MMU_STATE_SUP_RW  | _MMU_UX)
#define MMU_STATE_SUP_RX_USR_X     (MMU_STATE_SUP_RX  | _MMU_UX)
#define MMU_STATE_SUP_RWX_USR_X    (MMU_STATE_SUP_RWX | _MMU_UX)

#define MMU_STATE_SUP_R_USR_RX	   (MMU_STATE_SUP_R   | _MMU_UR | _MMU_UX)
#define MMU_STATE_SUP_RW_USR_RX    (MMU_STATE_SUP_RW  | _MMU_UR | _MMU_UX)
#define MMU_STATE_SUP_RX_USR_RX    (MMU_STATE_SUP_RX  | _MMU_UR | _MMU_UX)
#define MMU_STATE_SUP_RWX_USR_RX   (MMU_STATE_SUP_RWX | _MMU_UR | _MMU_UX)

#define MMU_STATE_SUP_R_USR_WX	   (MMU_STATE_SUP_R   | _MMU_UW | _MMU_UX)
#define MMU_STATE_SUP_RW_USR_WX    (MMU_STATE_SUP_RW  | _MMU_UW | _MMU_UX)
#define MMU_STATE_SUP_RX_USR_WX    (MMU_STATE_SUP_RX  | _MMU_UW | _MMU_UX)
#define MMU_STATE_SUP_RWX_USR_WX   (MMU_STATE_SUP_RWX | _MMU_UW | _MMU_UX)

#define MMU_STATE_SUP_R_USR_RWX	   (MMU_STATE_SUP_R   | _MMU_URWX)
#define MMU_STATE_SUP_RW_USR_RWX   (MMU_STATE_SUP_RW  | _MMU_URWX)
#define MMU_STATE_SUP_RX_USR_RWX   (MMU_STATE_SUP_RX  | _MMU_URWX)
#define MMU_STATE_SUP_RWX_USR_RWX  (MMU_STATE_SUP_RWX | _MMU_URWX)

/* RPN field offset in TLB Word 0 (left shift this number of bits) */

#define MMU_RPN_SHIFT				12

/* TLB_ENTRY_DESC page attributes */

#define _MMU_TLB_TS_0		0x00000000	/* Translation Space 0 */
#define _MMU_TLB_TS_1		0x00001000	/* Translation Space 1 */

#define _MMU_TLB_SZ_4K		0x00000100	/* 4KB page size */
#define _MMU_TLB_SZ_16K		0x00000200	/* 16KB page size */
#define _MMU_TLB_SZ_64K		0x00000300	/* 64KB page size */
#define _MMU_TLB_SZ_256K	0x00000400	/* 256KB page size */
#define _MMU_TLB_SZ_1M		0x00000500	/* 1MB page size */
#define _MMU_TLB_SZ_4M		0x00000600	/* 4MB page size */
#define _MMU_TLB_SZ_16M		0x00000700	/* 16MB page size */
#define _MMU_TLB_SZ_64M		0x00000800	/* 64MB page size */
#define _MMU_TLB_SZ_256M	0x00000900	/* 256MB page size */
#define _MMU_TLB_SZ_1G  	0x00000a00	/* 1GB page size */
#define _MMU_TLB_SZ_MASK	0x00000f00	/* mask for page size field */
#define _MMU_TLB_SZ_SHIFT	8		/* offset of page size field */

#define _MMU_TLB_ATTR_W		0x00000010	/* writethrough */
#define _MMU_TLB_ATTR_I		0x00000008	/* inhibit caching */
#define _MMU_TLB_ATTR_M		0x00000004	/* memory coherency */
#define _MMU_TLB_ATTR_G		0x00000002	/* guarded */
#define _MMU_TLB_ATTR_E		0x00000001	/* endianess */

#define _MMU_TLB_PERM_X		0x00000020	/* executable */
#define _MMU_TLB_PERM_W		0x00000040	/* writable */
#define _MMU_TLB_IPROT          0x00000080      /* invalidate protection */
#define _MMU_TLB_PERM_UR	0x00010000	/* user read */
#define _MMU_TLB_PERM_UW	0x00020000	/* user write */
#define _MMU_TLB_PERM_UX      	0x00040000	/* user execute */

#define TLB_GLOBAL_BIT	25	/* global page map bit is at bit 0 of word 2 */
#define TLB_LOCK_BIT	26	/* lock page map bit is at bit 1 of word 2 */


#define MMUE500_NUM_STATIC_TLB_ENTIRES 0x10

#ifndef _ASMLANGUAGE


/*
*
* E500 PTE descriptor definition 
* This stores most of the fields needed to update a TLB entry. Note that
* we store only 20 bits of the epn, since we support a minimum page size
* of 4K only. ERPN and variable page sizes are currently unimplemented.
*
* TLB fields are from ch. 6. PPCE500GP User's Manual, version 7, March
* 2002
*
* TLB Word 0:
*
*  0   1               8              16    19 20     24             31
* 32  33  34          40              48    51 52     56             63
* +-+-----+-+-+-+-+-+-'-+-+-+-+-+-+-+-'-+-+-+-+-+-+-+-'-+-+-+-+-+-+-+-+
* |V|IPROT|           |   TID         |     |T| TSIZE |               |
* | |     |           |               |     |S|       |               |
* +-+-----+-----------'---------------'---------------'-+-+-+-+-+-+-+-+
*
* V     - TLB Valid bit
* IPROT - Invalidate protect 
* TID   - Translation ID
* TS    - Translation space
* TSIZE - Translation size 
*
*
* TLB Word 1:
*
*  0               8              16      20  22      25          31
* 32              40              48      52  54      57          63
* +-+-+-+-+-+-+-+-'-+-+-+-+-+-+-+-'-+-+-+-+-+-+---+-'-+-+-+-+-+-+-+-+
* |                    EPN                |   |SHA|   |X|X|W|I|M|G|E|
* |                                       |   |REN|   |1|0| | | | | |
* +---------------'---------------'-------+-+-+---+-'-+-+-+-+-+-+-+-+
*
* EPN    - Effective (Virtual) address Page Number
* SHAREN - Enable cache fills to use shared cache state
* X0-X1  - Implementation dependant page attribute 
* W    	- Write-Through
* I    	- Caching Inhibited
* M    	- Memory Coherency required 
* G    	- Guarded
* E     - Endianess (Unused and set to zero.)
*
*
* TLB Word 2:
*
*  0               8              16      20  22      26          31
* 32              40              48      52  54      58          63
* +-+-+-+-+-+-+-+-'-+-+-+-+-+-+-+-'-+-+-+-+-+-+-+-'-+-+-+-+-+-+-+-+
* |                    RPN                |   | U0-U3 |U|S|U|S|U|S|
* |                                       |   |       |X|X|W|W|R|R|
* +---------------'---------------'-------+-+-+-+-'-+-+-+-+-+-+-+-+
*
* RPN    - Real (Physical) address Page Number
* U0-U3  - User bits
* UX     - User execute permission
* SX     - Supervisor execute permission
* UW     - User write permission
* SW     - Supervisor write permission
* UR     - User read permission
* SR     - Supervisor read permission
*
*
*/

typedef union e500_pte	/* e500 pte format */
    {
    struct			/* Bit field description */
	{
	/* word 0 */
	UINT32 v:1;		/* valid bit */
	UINT32 iprot:1;		/* invalidate protect bit */
	UINT32 rsvd1:6;		/* reserved */
	UINT32 tid:8;		/* translation ID */
	UINT32 rsvd2:3;		/* reserved */
	UINT32 ts:1;		/* translation space */
	UINT32 tsize:4;		/* translation size */
	UINT32 rsvd3:8;		/* reserved */

	/* word 1 */
	UINT32 epn:20;		/* effective page number */
	UINT32 rsvd4:2;		/* reserved */
	UINT32 sharen:1;        /* enables cache fills to use shared cache state */
	UINT32 rsvd5:2;		/* reserved */
	UINT32 global:1;	/* global bit for internal use */
	UINT32 lock:1;          /* lock bit label indicating static TLB used */
	UINT32 w:1;		/* write thru/back */
	UINT32 i:1;		/* cache inhibited */
	UINT32 m:1;		/* memory coherent */
	UINT32 g:1;		/* memory guarded  */
	UINT32 e:1;		/* little endian bit */

	/* word 2 */
	UINT32 rpn:20;		/* real page number */
	UINT32 rsvd6:2;		/* reserved */
	UINT32 u0:1;		/* user attribute 0 */
	UINT32 u1:1;		/* user attribute 1 */
	UINT32 u2:1;		/* user attribute 2 */
	UINT32 u3:1;		/* user attribute 3 */
	UINT32 ux:1;		/* user execute protection */
	UINT32 sx:1;		/* supervisor execute protection */
	UINT32 uw:1;		/* user write protection */
	UINT32 sw:1;		/* supervisor write protection */
	UINT32 ur:1;		/* user read protection */
	UINT32 sr:1;		/* supervisor read protection */
	/* word3 */
#if defined(PPC_e500v2)
	UINT32 rsvd7:28;	/* reserved*/
	UINT32 erpn:4;	        /* extended real page number*/
#else
	UINT32 rsvd7:32;	/* pad descriptor table to power of 2 */
#endif
	} field;

    struct 
	{
	UINT32 word0;		/* word 0 */
	UINT32 word1;		/* word 1 */
	UINT32 word2;		/* word 2 */
#if defined(PPC_e500v2)
	UINT32 word3;		/* word3 */
#else
	UINT32 pad0;		/* pad word */
#endif
	} words;

    } MMUE500_PTE;

/* TLB Entry description, used for mmu initialization */

typedef struct
    {
    UINT32	effAddr;	/* Effective address of base of page */
    UINT32	realAddrExt;	/* top 4 bits of real address */
    UINT32	realAddr;	/* rest of real address */
    UINT32	attr;		/* page attributes */
    } TLB_ENTRY_DESC;


#if defined(__STDC__) || defined(__cplusplus)

extern STATUS mmuE500LibInit (int mmuType, int staticTlbNum, TLB_ENTRY_DESC * pStaticTlbDesc);

#else   /* __STDC__ */

extern STATUS mmuE500LibInit ();

#endif  /* __STDC__ */

#endif /* _ASMLANGUAGE */

#ifdef __cplusplus
}
#endif

#endif /* __INCmmuPpcE500Libh */
